package racer.server;

import java.io.IOException;
import java.nio.BufferOverflowException;
import java.nio.charset.CharacterCodingException;
import java.nio.channels.SocketChannel;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;

public class Player {

	private static final int BUFSIZE = 512;
	private static final String CHARSET = "ISO-8859-1";
	
	private int id;
	private SocketChannel sockChann;
	private ByteBuffer buffin;
	private Charset charset;
	private CharsetDecoder decoder;
	private RaceServer rc;
	
	public Player(int id, SocketChannel sockChann, RaceServer rc) {
		this.id = id;
		this.rc = rc;
		this.sockChann = sockChann;
		buffin = ByteBuffer.allocateDirect(BUFSIZE);
		buffin.clear();
		
		charset = Charset.forName(CHARSET);
		decoder = charset.newDecoder();
	}
	
	public String recvMessage() {
		String msg = null;
		try {
			int numBytesRead = sockChann.read(buffin);
			if (numBytesRead == -1) {
				rc.removeChannel(sockChann, this.id);
				return null;
			}
			msg = getMessage(buffin);
		} catch (IOException io) {
			io.printStackTrace();
		}
		
		return msg;
	}
	
	// TODO What if the buffer contains last part of one message and (first part of) a second message?
	private String getMessage(ByteBuffer buf) {
		String msg = null;
		int pos = buf.position();
		int limit = buf.limit();
		
		// set buffer limit to last byte, not necessarily last place in buffer
		// aka buf.flip()
		buf.position(0);
		buf.limit(pos);
		
		// bytebyffer --> charbuffer --> string
		try {
			CharBuffer charbuff = decoder.decode(buf);
			msg = charbuff.toString();
		} catch (CharacterCodingException e) {
			e.printStackTrace();
		}
		//msg.replaceAll("\n", "");
		//bufferMessage+=msg;
		
		// return buffer to full capacity state
		buf.limit(limit);
		buf.position(pos);
		buf.clear();
		
		System.out.println("Read from buffer: " + msg);
		return msg;
		/*
		// if message ends with newline: end of message, return message and clear buffer
		//if(msg.endsWith("\n")) {
		//	buf.clear();
		//	return msg;
		//}
		int firstPos = bufferMessage.indexOf(DELIM);
		int lastPos = bufferMessage.indexOf(DELIM, firstPos+1);
		if(lastPos != -1) {
			String retmsg = bufferMessage.substring(firstPos, lastPos  + DELIM.length());
			bufferMessage = bufferMessage.substring(lastPos + DELIM.length());
			return retmsg;
		} else {
			
		}
		// message is not complete yet
		return null;
		*/
	}
	
	public boolean sendMessage(String msg) {
		String fullmsg = msg + "\n";
		boolean msgSent = false;
		
		ByteBuffer buffout = ByteBuffer.allocateDirect(BUFSIZE);
		buffout.clear();
		try {
			buffout.put(fullmsg.getBytes());
		} catch (BufferOverflowException e) {
			e.printStackTrace();
		}
		buffout.flip();
		
		try {
			while(buffout.hasRemaining()) {
				sockChann.write(buffout);
			}
			msgSent = true;
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		return msgSent;
	}
	
	public SocketChannel getSockChann() {
		return this.sockChann;
	}

	public int getId() {
		return id;
	}
	
}
